/*
 * @Author: xiaosihan
 * @Date: 2023-09-01 00:09:29
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2023-12-22 00:50:36
 */

import { fabric } from 'fabric';
import { TextOptions } from 'fabric/fabric-impl';
import fontManage from './fontManage';
import { flattenDeep } from 'lodash';
import { degToRad } from 'three/src/math/MathUtils.js';

// 文字组件
export default class FabricText extends fabric.IText {
  constructor(text: string = 'FabricText', options: TextOptions & { bendDegree?: number } = {}) {
    super(text, options);
    this.name = options.name || '';
    this.editable = !['name', 'num'].includes(this.name);
    this.strokeWidth = options.strokeWidth || 0;
    this.originWidth = this.width!;
    this.originHeight = this.height!;
    this.bendDegree = options.bendDegree || 0;
    // 默认字体
    this.fontFamily = options.fontFamily || fontManage.fontlist[0].id;
    // 设置控制器都不可见
    this.setControlsVisibility({
      tl: true,
      tr: true,
      bl: true,
      br: true,
      mb: false,
      ml: false,
      mr: false,
      mt: false,
    });
    this.initDimensions();
    this._updatePath();
  }

  //原始宽高 在名字和号码的预览功能会用到，保持原有文字的宽度
  originWidth = 400;
  originHeight = 100;
  stroke = '#000000';
  bendDegree = 0; //文字弯曲的角度

  name = '';

  // 可以不导出的默认值
  static defaultOption = {
    angle: 0,
    backgroundColor: '',
    charSpacing: 0,
    direction: 'ltr',
    fill: 'rgb(0,0,0)',
    fillRule: 'nonzero',
    flipX: false,
    flipY: false,
    fontStyle: 'normal',
    fontWeight: 'normal',
    globalCompositeOperation: 'source-over',
    linethrough: false,
    opacity: 1,
    originX: 'center',
    originY: 'center',
    overline: false,
    paintFirst: 'fill',
    path: null,
    pathAlign: 'baseline',
    pathSide: 'left',
    pathStartOffset: 0,
    scaleX: 1,
    scaleY: 1,
    shadow: null,
    skewX: 0,
    skewY: 0,
    stroke: null,
    strokeDashArray: null,
    strokeDashOffset: 0,
    strokeLineCap: 'butt',
    strokeLineJoin: 'miter',
    strokeMiterLimit: 4,
    strokeUniform: false,
    strokeWidth: null,
    styles: [],
    textAlign: 'left',
    textBackgroundColor: '',
    underline: false,
    visible: true,
  };

  declare id: string;

  declare text: string;

  originX = 'center';

  originY = 'center';

  // objectCaching = false;

  noScaleCache = false;

  // 缩小时不翻转
  lockScalingFlip = true;

  //  同时处理文字元素  最小宽高, 取消全选不跑偏问题
  setPositionByOrigin(pos: any, originX: any, originY: any) {
    var center = super.translateToCenterPoint(pos, originX, originY),
      position = super.translateToOriginPoint(center, this.originX, this.originY);
    if (this.canvas && this.canvas.getActiveObject() !== this) {
      super.set('left', position.x);
      super.set('top', position.y);
    }
  }

  // _styles = {};
  // set styles(v) {
  //   debugger;
  //   this._styles = v;
  // }
  // get styles() {
  //   debugger;
  //   return this._styles;
  // }

  set(...options: Array<any>) {
    console.log(options);

    //@ts-ignore
    const object = super.set(...options);

    if (['name', 'num'].includes(this.name) && ['scaleX', 'scaleY'].includes(options[0])) {
      this.originWidth = this.width!;
      this.originHeight = this.height!;
    }

    if (
      ['fontFamily', 'fontSize', 'charSpacing', 'lineHeight', 'bendDegree'].includes(options[0])
    ) {
      this._updatePath();
    }

    this.styles = {};

    return object;
  }

  // 计算元素的宽高
  initDimensions() {
    super.initDimensions();
    if (this.path) {
      this.width! += this.fontSize! * 1.5 * Math.sin(degToRad(Math.min(180, this.bendDegree) / 2));
      if (this.bendDegree > 0) {
        this.height! += this.fontSize! * 1.5;
      }
    }
  }

  // 绘制弯曲的文字
  _updatePath() {
    // 定义参数
    const angle = this.bendDegree; // 弧的夹角（单位：度）
    let chordLength = this._textLines ? this.measureLine(0).width : 0; // 文字总长度
    // 计算半径
    const radius = chordLength / (2 * Math.PI * (angle / 360));
    // 计算弧的起始点和结束点
    const startX = Math.sin(degToRad(angle / 2)) * -radius;
    const startY = 0;

    const endX = Math.sin(degToRad(angle / 2)) * radius;
    const endY = 0;

    // 创建路径
    const path = new fabric.Path(
      `M ${startX},${startY} A ${radius},${radius},0,${angle < 180 ? '0' : '1'},1,${endX},${endY}`,
      {
        stroke: '#00000000',
        fill: '#00000000',
        strokeWidth: 2,
      },
    );

    if (angle === 0) {
      this.set('path', null);
    } else if (chordLength > 0 && angle > 0) {
      this.set({ path });
    }
  }

  toObject(propertiesToInclude: string[] = []) {
    const object = super.toObject([
      ...propertiesToInclude,
      'name',
      'originWidth',
      'originHeight',
      'bendDegree',
    ]);
    Object.assign(object, { styles: {} }); // 暂时先不支持单个文字样式
    delete object.path; // 暂时先不支持路径
    return object;
  }

  toJSON(propertiesToInclude: string[] = []): {
    version: string;
    objects: fabric.Object[];
  } {
    const json = super.toJSON([
      ...propertiesToInclude,
      'name',
      'originWidth',
      'originHeight',
      'bendDegree',
    ]);
    Object.assign(json, { styles: {} }); // 暂时先不支持单个文字样式
    return json;
  }
}

fabric.IText = FabricText;
